package both.map.mapModel.unitTests;

import junit.framework.Assert;

import org.junit.Test;

import both.map.mapModel.ModelActor;
import both.map.mapModel.TokenCell;

public class TokenCellTest {

	/**
	 * testing against runtime problems with constructor
	 */
	@Test
	public void testTokenCell() 
	{
		@SuppressWarnings("unused")
		TokenCell tc = new TokenCell();
	}

	/**
	 * testing addActor Method
	 */
	@Test
	public void testAddActor() 
	{
		TokenCell tc = new TokenCell();
		Assert.assertEquals(0, tc.getAllActors().size());
		ModelActor actor = new ModelActor(null);
		tc.addActor(actor);
		Assert.assertTrue(tc.containsActor(actor));
		Assert.assertEquals(1, tc.getAllActors().size());
		ModelActor actor2 = new ModelActor(null);
		tc.addActor(actor2);
		Assert.assertTrue(tc.containsActor(actor2));
		Assert.assertEquals(2, tc.getAllActors().size());
		// make sure the first actor is still there...
		Assert.assertTrue(tc.containsActor(actor));
	}
	
	/**
	 * testing addActor when an actor is sent to it which is 
	 * already there
	 */
	@Test
	public void testAddActorAddActorAlreadyPresent()
	{
		TokenCell tc = new TokenCell();
		ModelActor actor = new ModelActor(null);
		ModelActor actor2 = new ModelActor(null);
		tc.addActor(actor);
		tc.addActor(actor2);
		Assert.assertFalse(tc.addActor(actor));
		Assert.assertEquals(2, tc.getAllActors().size());
		Assert.assertFalse(tc.addActor(actor2));
		Assert.assertEquals(2, tc.getAllActors().size());
	}
	
	/**
	 * testing removeActor()
	 */
	@Test
	public void testRemoveActor() 
	{
		TokenCell tc = new TokenCell();
		ModelActor actor = new ModelActor(null);
		ModelActor actor2 = new ModelActor(null);
		
		Assert.assertEquals(0,tc.getAllActors().size());
		Assert.assertFalse(tc.containsActor(actor));
		Assert.assertFalse(tc.containsActor(actor2));
		
		tc.addActor(actor);
		
		Assert.assertEquals(1,tc.getAllActors().size());
		Assert.assertTrue(tc.containsActor(actor));
		
		tc.removeActor(actor);
		
		Assert.assertEquals(0,tc.getAllActors().size());
		Assert.assertFalse(tc.containsActor(actor));
		
		tc.addActor(actor);
		tc.addActor(actor2);
		
		Assert.assertEquals(2, tc.getAllActors().size());
		Assert.assertTrue(tc.containsActor(actor));
		Assert.assertTrue(tc.containsActor(actor2));
		
		tc.removeActor(actor2);
		
		Assert.assertEquals(1, tc.getAllActors().size());
		Assert.assertTrue(tc.containsActor(actor));
		Assert.assertFalse(tc.containsActor(actor2));
		
		tc.addActor(actor2);
		tc.removeActor(actor);
		
		Assert.assertEquals(1, tc.getAllActors().size());
		Assert.assertFalse(tc.containsActor(actor));
		Assert.assertTrue(tc.containsActor(actor2));
		
		tc.removeActor(actor2);
		
		Assert.assertEquals(0,tc.getAllActors().size());
		Assert.assertFalse(tc.containsActor(actor));
		Assert.assertFalse(tc.containsActor(actor2));
	}
	
	/**
	 * test removeActor() for actor not present
	 */
	@Test
	public void testRemoveActorWhenActorNotPresent()
	{
		TokenCell tc = new TokenCell();
		ModelActor actor = new ModelActor(null);
		
		Assert.assertFalse(tc.removeActor(actor));
		Assert.assertEquals(0,tc.getAllActors().size());
		
		tc.addActor(actor);
		Assert.assertEquals(1,tc.getAllActors().size());
		Assert.assertTrue(tc.removeActor(actor));
		Assert.assertEquals(0,tc.getAllActors().size());
		
	}

	@Test
	public void testGetAllActors() {
		TokenCell tc = new TokenCell();
		ModelActor actor = new ModelActor(null);
		ModelActor actor2 = new ModelActor(null);
		
		tc.addActor(actor);
		
		Assert.assertEquals(1,tc.getAllActors().size());
		Assert.assertTrue(tc.getAllActors().contains(actor));
		Assert.assertFalse(tc.getAllActors().contains(actor2));
		
		tc.addActor(actor2);
		
		Assert.assertEquals(2,tc.getAllActors().size());
		Assert.assertTrue(tc.getAllActors().contains(actor));
		Assert.assertTrue(tc.getAllActors().contains(actor2));
		
		tc.removeActor(actor);
		
		Assert.assertEquals(1,tc.getAllActors().size());
		Assert.assertFalse(tc.getAllActors().contains(actor));
		Assert.assertTrue(tc.getAllActors().contains(actor2));
	}

	@Test
	public void testContainsActor() {
		// Just to highlight the point - AddActor and RemoveActor tests ContainsActor as well.
		testAddActor();
		testRemoveActor();
	}

	@Test
	public void testNoOfActors() {
		TokenCell tc = new TokenCell();
		ModelActor actor = new ModelActor(null);
		ModelActor actor2 = new ModelActor(null);
		
		tc.addActor(actor);
		
		Assert.assertEquals(1,tc.noOfActors());
		Assert.assertEquals(tc.getAllActors().size(), tc.noOfActors());
		
		tc.addActor(actor2);
		
		Assert.assertEquals(2,tc.noOfActors());
		Assert.assertEquals(tc.getAllActors().size(), tc.noOfActors());
		
		tc.removeActor(actor);
		
		Assert.assertEquals(1,tc.noOfActors());
		Assert.assertEquals(tc.getAllActors().size(), tc.noOfActors());
	}

	@Test
	public void testGrabUpdate() {
		TokenCell tc = new TokenCell();
		
		Assert.assertNull(tc.grabUpdate());
		
		ModelActor actor = new ModelActor(null);
		tc.addActor(actor);
		
		TokenCell update = tc.grabUpdate();
		Assert.assertNotNull(update);
		Assert.assertNotSame(tc, update);
		Assert.assertEquals(tc.noOfActors(), update.noOfActors());
		Assert.assertEquals(tc.containsActor(actor), update.containsActor(actor));
		Assert.assertEquals(tc.getAllActors(), update.getAllActors());
		
		Assert.assertNull(tc.grabUpdate());
	}
	
	@Test
	public void testApplyUpdate() {
		TokenCell tc = new TokenCell();
		ModelActor a1 = new ModelActor(null);
		ModelActor a2 = new ModelActor(null);
		tc.addActor(a1);
		TokenCell update = tc.grabUpdate();
		
		TokenCell recipient = new TokenCell();
		recipient.addActor(a1);
		recipient.addActor(a2);
		Assert.assertTrue(recipient.containsActor(a1));
		Assert.assertTrue(recipient.containsActor(a2));
		Assert.assertTrue(update.containsActor(a1));
		Assert.assertFalse(update.containsActor(a2));
		
		recipient.applyUpdate(update);
		
		Assert.assertTrue(recipient.containsActor(a1));
		Assert.assertFalse(recipient.containsActor(a2));
		
		recipient.addActor(a2);
		recipient.removeActor(a1);
		recipient.applyUpdate(recipient.grabUpdate());
		
		Assert.assertFalse(recipient.containsActor(a1));
		Assert.assertTrue(recipient.containsActor(a2));
		
		recipient.removeActor(a2);
		
		recipient.applyUpdate(recipient.grabUpdate());
		
		Assert.assertFalse(recipient.containsActor(a1));
		Assert.assertFalse(recipient.containsActor(a2));
		
		TokenCell update2 = recipient.grabUpdate();
		
		Assert.assertNull(update2);
		
		recipient.applyUpdate(update2);
		Assert.assertFalse(recipient.containsActor(a1));
		Assert.assertFalse(recipient.containsActor(a2));
		
	}
}
